﻿//AcademicPlanner - course registration planning web app.
//Copyright (C) 2009  Boubacar Diallo

//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.


using System;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace AcademicPlanner.Framework.Helpers
{
	/// <summary>
	/// SecurityHelper provides static helper methods for web security.
	/// </summary>
	/// <since>1.0</since>
	public static class SecurityHelper
	{
		/// <summary>
		/// Hashes the given text using MD5.
		/// </summary>
		/// <param name="pText">The text to hash.</param>
		/// <param name="pSalt">The salt to use in the hash.</param>
		/// <returns>The hashed text and the salt.</returns>
		/// <since>1.0</since>
		public static string Hash(string pText, string pSalt)
		{
			string rHash = "";
			var vHasher = new MD5CryptoServiceProvider();
			var vTextBytes = Encoding.UTF8.GetBytes(pText);
			var vSaltBytes = Encoding.UTF8.GetBytes(pSalt);
			var vBytesToHash = new byte[vTextBytes.Length + vSaltBytes.Length];

			for (int i = 0; i < vTextBytes.Length; i++)
				vBytesToHash[i] = vTextBytes[i];

			for (int i = 0; i < vSaltBytes.Length; i++)
				vBytesToHash[vTextBytes.Length + i] = vSaltBytes[i];

			var vHashed = vHasher.ComputeHash(vBytesToHash);
			var vHash = new byte[vHashed.Length + vSaltBytes.Length];

			for (int i = 0; i < vHashed.Length; i++)
				vHash[i] = vHashed[i];

			for (int i = 0; i < vSaltBytes.Length; i++)
				vHash[vHashed.Length + i] = vSaltBytes[i];

			rHash = Convert.ToBase64String(vHash);

			return rHash;
		}

		/// <summary>
		/// Returns a random unique hash obtained from <c>Guid.NewGuid</c>.
		/// </summary>
		/// <returns>A random unique hash.</returns>
		/// <since>1.0</since>
		public static string RandomHash()
		{
			return Convert.ToBase64String(Guid.NewGuid().ToByteArray());
		}

		/// <summary>
		/// Encodes a string to be safely used as a url.
		/// </summary>
		/// <param name="pString">The string to encode.</param>
		/// <returns>The encoded string.</returns>
		/// <since>1.0</since>
		public static string UrlEncode(string pString)
		{
			return HttpContext.Current.Server.UrlEncode(pString);
		}

		/// <summary>
		/// Decodes a url encoded string.
		/// </summary>
		/// <param name="pString">The string to decode.</param>
		/// <returns>The decoded string.</returns>
		/// <since>1.0</since>
		public static string UrlDecode(string pString)
		{
			return HttpContext.Current.Server.UrlDecode(pString);
		}

		/// <summary>
		/// Strips all html tags from a string.
		/// </summary>
		/// <remarks>
		/// This method does nothing sophisticated and simply
		/// replaces the regex <c>&lt;(.|\n)*?&gt;</c> with
		/// <c>string.Empty</c>.
		/// </remarks>
		/// <param name="pString"></param>
		/// <returns>The string with all html tags removed.</returns>
		/// <since>1.0</since>
		public static string StripHTML(string pString)
		{
			return Regex.Replace(pString, @"<(.|\n)*?>", string.Empty);
		}

		/// <summary>
		/// Sanitizes web user input.
		/// </summary>
		/// <remarks>
		/// This method simply calls <see cref="M:StripHTML"/> on
		/// <paramref name="pInput"/>.
		/// </remarks>
		/// <param name="pInput">The input to sanitize.</param>
		/// <returns>The sanitized input.</returns>
		/// <since>1.0</since>
		public static string SanitizeInput(string pInput)
		{
			return StripHTML(pInput);
		}

		/// <summary>
		/// Escapes single quotes in a string.
		/// </summary>
		/// <param name="pString">The string to escape.</param>
		/// <returns>The string with single quotes escaped.</returns>
		/// <since>1.0</since>
		public static string EscapeSingleQuotes(string pString)
		{
			return pString.Replace("'", @"\'");
		}

		/// <summary>
		/// Escapes double quotes in a string.
		/// </summary>
		/// <param name="pString">The string to escape.</param>
		/// <returns>The string with double quotes escaped.</returns>
		/// <since>1.0</since>
		public static string EscapeDoubleQuotes(string pString)
		{
			return pString.Replace(@"""", @"\""");
		}

		/// <summary>
		/// Escapes slashes in a string.
		/// </summary>
		/// <param name="pString">The string to escape.</param>
		/// <returns>The string with slashes escaped.</returns>
		/// <since>1.0</since>
		public static string EscapeSlashes(string pString)
		{
			return pString.Replace(@"\", @"\\");
		}

		/// <summary>
		/// Escapes slashes and quotes in a string.
		/// </summary>
		/// <param name="pString">The string to escape.</param>
		/// <returns>The string with slashes and quotes escaped.</returns>
		/// <since>1.0</since>
		public static string Escape(string pString)
		{
			var rString = EscapeSlashes(pString);

			rString = EscapeDoubleQuotes(rString);
			rString = EscapeSingleQuotes(rString);

			return rString;
		}
	}
}
